﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using ProgNetComponents.Utils;

namespace ProgNetComponents.Validation.Rules
{
    /// <summary>
    /// Rule for checking if all columns are unique
    /// </summary>
    public class MultiColumnsUniqueValidationRule : MultiColumnsValidationRule, IFilterValidationRule, IStopOnFirstErrorValidationRule
    {
        #region Static
        /// <summary>
        /// Initializes the <see cref="MultiColumnsUniqueValidationRule"/> class.
        /// </summary>
        static MultiColumnsUniqueValidationRule()
        {
            GlobalDefaultErrorString = "Ta wartość powinna być unikalna.";
        }
        /// <summary>
        /// Gets or sets the global default error string.
        /// </summary>
        /// <value>
        /// The global default error string.
        /// </value>
        public static string GlobalDefaultErrorString { get; set; }
        #endregion

        #region Properties

        /// <summary>
        /// Gets default error string
        /// </summary>
        /// <value>
        /// The default error string.
        /// </value>
        protected override string DefaultErrorString
        {
            get
            {
                return GlobalDefaultErrorString;
            }
        }

        /// <summary>
        /// Gets or sets Filter used for selecting rows to compare
        /// </summary>
        /// <value>
        /// The filter.
        /// </value>
        public string Filter
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets if validation should stop on first error
        /// </summary>
        /// <value>
        ///   <c>true</c> if [stop on first error]; otherwise, <c>false</c>.
        /// </value>
        public bool StopOnFirstError
        {
            get;
            set;
        }

        /// <summary>
        /// Specifies how nulls will be compared
        /// <para> True - null is equal to everything</para>
        /// <para> Fals - null is not equal to anything</para>
        /// <para> Default - null is equal to null only</para>
        /// </summary>
        /// <value>
        /// The nulls are equal.
        /// </value>
        public DefaultBool NullsAreEqual
        {
            get;
            set;
        }

        #endregion

        /// <summary>
        /// Initializes a new instance of the <see cref="MultiColumnsUniqueValidationRule"/> class.
        /// </summary>
        public MultiColumnsUniqueValidationRule()
        {
            Filter = null;
            StopOnFirstError = true;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="MultiColumnsUniqueValidationRule"/> class.
        /// </summary>
        /// <param name="columns">The columns.</param>
        /// <param name="error">The error.</param>
        public MultiColumnsUniqueValidationRule(string[] columns, string error = null)
            : base(columns, error)
        {
            Filter = null;
            StopOnFirstError = true;
        }

        /// <summary>
        /// The rows to validate
        /// </summary>
        private DataRow[] rowsToValidate = null;
        /// <summary>
        /// Clears the validation settings.
        /// </summary>
        public override void ClearValidationSettings()
        {
            rowsToValidate = null;
        }
        /// <summary>
        /// Does the validate.
        /// </summary>
        /// <param name="row">The row.</param>
        /// <returns></returns>
        protected override bool DoValidate(DataRow row)
        {
            bool result = true;
           if(rowsToValidate ==null)
               rowsToValidate  = row.Table.Select(Filter);
           foreach (DataRow r in rowsToValidate)
            {
                if (r == row)
                    continue;
               
                foreach (string column in Columns)
                {
                    bool thesame = true;

                    if (r[column].IsNull() || row[column].IsNull())
                    {
                        switch (NullsAreEqual)
                        {
                            case DefaultBool.Default:
                                thesame = r[column].IsTheSame(row[column]);
                                break;
                            case DefaultBool.True:
                                thesame = true;
                                break;
                            case DefaultBool.False:
                                thesame = false;
                                break;
                            default:
                                break;
                        }
                    }
                    else
                    {
                        thesame = r[column].IsTheSame(row[column]);
                    }
                    if (thesame)
                    {
                        result = false;
                        r.SetColumnError(column, FormatedErrorString);
                        row.SetColumnError(column, FormatedErrorString);
                        if (StopOnFirstError)
                            return result;
                    }
                }
            }
            return result;
        }
        /// <summary>
        /// Called when [validation failed].
        /// </summary>
        /// <param name="row">The row.</param>
        protected override void OnValidationFailed(DataRow row)
        {
            
        }
    }
    
}
